package com.jwyming.secKilling;

import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.message.BasicNameValuePair;
import org.apache.log4j.Logger;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.*;


/**
 * Created by user on 2017/4/1.
 */
public class Utils {
    static Logger logger = Logger.getLogger(Utils.class.getName());

    public static Map<String, List<NameValuePair>> getForms(
            StringBuffer html)
            throws UnsupportedEncodingException {
//        logger.info("得到所有表单...");
        Document doc = Jsoup.parse(html.toString());
        Elements forms = doc.getElementsByTag("form");
        Map<String, List<NameValuePair>> formMap = new HashMap<String, List<NameValuePair>>();

        for(Element formElement : forms) {
            String action = formElement.attr("action");
            List<NameValuePair> paramList = new ArrayList<NameValuePair>();

            Elements inputElements = formElement.getElementsByTag("input");
            for (Element inputElement : inputElements) {
                String key = inputElement.attr("name");
                String value = inputElement.attr("value");
                paramList.add(new BasicNameValuePair(key, value));

            }

            Elements textareaElements = formElement.getElementsByTag("textarea");
            for (Element textareaElement : textareaElements) {
                String key = textareaElements.attr("name");
                String value = textareaElements.attr("value");
                paramList.add(new BasicNameValuePair(key, value));

            }

            Elements selectElements = formElement.getElementsByTag("select");
            for (Element selectElement : selectElements) {
                String key = selectElement.attr("name");
                Elements options = selectElement.select("option");
                List<String> values = new ArrayList<String>();
                for(Element element : options) {
                    values.add(element.attr("value"));
                }
                logger.info("select name = " + key + ",values = " + values);
                paramList.add(new BasicNameValuePair(key, values.get(values.size()-1)));

            }

            formMap.put(action, paramList);
        }
        return formMap;
    }

    public static List<String> getUrls(StringBuffer  html) {
        logger.info("得到页面所有URL。。。");
        List<String> urls = new ArrayList<String>();
        Document doc = Jsoup.parse(html.toString());
        Elements urlElements = doc.getElementsByTag("a");
        for(Element urlElement : urlElements) {
            String href = urlElement.attr("href");
            if(href != null && !href.equals("#")) {
                urls.add(href);
            }
        }
        return urls;
    }


    public static Form getActionForm(StringBuffer pageContent, String formActionMatcher) throws Exception {
        // 得到所有表单
        Map<String, List<NameValuePair>> forms = Utils.getForms(pageContent);
        Form form = null;
        logger.info("找到需要的表单。。。");
        //        找到特定actionUrl的表单
        for(String key  : forms.keySet()) {
            if(key.contains(formActionMatcher)) {
                form = new Form(key, forms.get(key));
                break;
            }
        }
        return form;
    }


    public static Form updateForm(Form form, HashMap<String, Object> myParams, int executeTimes) throws Exception {
        logger.info("更新表单信息。。。");
        Form updatedForm = form;

//        替换表单需要输入的元素
        ListIterator<NameValuePair> iter = updatedForm.getParams().listIterator();
        while(iter.hasNext()){
            NameValuePair nameValuePair = iter.next();
            String name = nameValuePair.getName();
            if(myParams.containsKey(name)) {
                iter.remove();
                Object valueObj = myParams.get(name);
                if(valueObj instanceof String) {
                    iter.add(new BasicNameValuePair(name, (String) myParams.get(name)));
                } else if(valueObj instanceof List) {
                    List<String> valueList = (List<String>) myParams.get(name);
                    int index = executeTimes % valueList.size();
//                    logger.info("valueList.size() = " + valueList.size() + ", executeTimes=" + executeTimes);
                    iter.add(new BasicNameValuePair(name, valueList.get(index)));
                }
            }
        }

//        打印表单信息
//        Utils.printForm(updatedForm.getActionUrl(), updatedForm.getParams());

        return updatedForm;
    }

    public static StringBuffer sendPost(HttpClient client, String url, List<NameValuePair> postParams)
            throws Exception {
//        url = getUniformedUrl(url);
        logger.info("发送POST表单请求到URL : " + url);
        logger.info("表单参数 : " + postParams);
        HttpPost post = new HttpPost(url);
        post.setEntity(new UrlEncodedFormEntity(postParams));

        HttpResponse response = client.execute(post);
        int responseCode = response.getStatusLine().getStatusCode();
        if(responseCode == HttpStatus.SC_OK) {

//            logger.info("正常响应码 : " + responseCode);
            BufferedReader rd = new BufferedReader(
                    new InputStreamReader(response.getEntity().getContent()));
            StringBuffer result = new StringBuffer();
            String line = "";
            while ((line = rd.readLine()) != null) {
                result.append(line);
            }
//            logger.info("================= page content: ==================");
//            logger.info(result);
//            logger.info("========================================================");
            return result;
        } else {
            logger.error("异常响应码 : "+ responseCode);
            throw new Exception();
        }
    }


    public static StringBuffer getPageContent(HttpClient client, String url) throws Exception {
//        url = getUniformedUrl(url);
        logger.info("获取页面内容， URL = " + url);
        HttpGet request = new HttpGet(url);
        HttpResponse response = client.execute(request);
        int responseCode = response.getStatusLine().getStatusCode();

        if(responseCode == HttpStatus.SC_OK) {
//            logger.info("正常响应码： " + responseCode);
            BufferedReader rd = new BufferedReader(
                    new InputStreamReader(response.getEntity().getContent()));

            StringBuffer result = new StringBuffer();
            String line = "";
            while ((line = rd.readLine()) != null) {
                result.append(line);
            }
//            logger.info("================= page content: ==================");
//            logger.info(result);
//            logger.info("========================================================");

            return result;
        } else {
            logger.error("异常响应码 : "+ responseCode);
            throw new Exception();
        }
    }

    public static void printForm(Form form) {
//        actionUrl = getUniformedUrl(actionUrl);
        logger.info("打印表单。。。");
        logger.info("action = " + form.getActionUrl());
        for(NameValuePair nameValuePair : form.getParams()) {
            logger.info("参数: name=" + nameValuePair.getName() + ", value=" + nameValuePair.getValue());
        }
    }

    public static void printForms(List<Form> forms) {
        for (Form form : forms) {
            printForm(form);
        }
    }

//    private static String getUniformedUrl(String url) {
//        String uniformedUrl = url;
//        if(!uniformedUrl.startsWith("http")) {
//            uniformedUrl = ConfigItem.getInstance().getProperty("DOMAIN_URL") + url;
//        }
//        return uniformedUrl;
//    }

    public static void printUrls(List<String> urls) {
        logger.info("打印所有的URL: ");
        for(String url : urls) {
            logger.info(" url:  " + url);
        }
    }
}
